#ifndef APP_WIFI_TEST_H
#define APP_WIFI_TEST_H
#include <kernel/sign_kernel.h>
#include <string/UartString.h>
// /* 大小端模式 */
// #define BIG_ENDIAN_MODE
// #ifdef BIG_ENDIAN_MODE
// // #define UINT16_T struct UINT16_STRUCT{uint8_t H; uint8_t L; }
// typedef struct UINT16_STRUCT { uint8_t H; uint8_t L; } UINT16_T;
// #else
// // #define UINT16_T struct UINT16_STRUCT{uint8_t L; uint8_t H; }
// typedef struct UINT16_STRUCT { uint8_t L; uint8_t H; } UINT16_T;
// #endif

#define BIG_ENDIAN_MODE
class UINT16_T { 
public:
    /* 大小端模式 */
    #ifdef BIG_ENDIAN_MODE
    uint8_t H; 
    uint8_t L; 
    #else
    uint8_t L; 
    uint8_t H; 
    #endif

    uint16_t getValue() {
        return ((uint16_t)H << 8) | L;
    }
};

#define WIFI_COMM_HEADER_H        0XF4 /* 包头 */
#define WIFI_COMM_HEADER          0XF4F5 /* 包头 */
#define WIFI_COMM_TYPE_DEF        0X0000 /* 默认值 */
#define WIFI_COMM_TYPE_ZKW        0X1401 /* ZKW-Z3M7.i */
#define WIFI_COMM_STAT_REQUEST    0X01 /* 命令请求 */
#define WIFI_COMM_STAT_RESPONSE   0X02 /* 命令响应 */
#define WIFI_COMM_FLAGS           0X0000 /* Flags 预留 */
#define WIFI_TYPE_FLAGS_LEN       0X08 
#define WIFI_LENGTH_MAX_VALUE     0XC0
#define WIFI_COMM_MAX_PAYLOAD_NUM 0XB8 /* 最大PAYLOAD长度 */

typedef enum WIFI_CMD_LIST {
    /* 通用命令 */
    WIFI_CMD_REQUEST_DEVICE_INFO = 0X01, /* 请求设备信息 */
    WIFI_CMD_WIFI_STATE_CHANGE   = 0X03, /* WIFI模组状态发生变化 */
    WIFI_CMD_WIFI_CONFIGURATIONS = 0X04, /* MCU配置WIFI */
    WIFI_CMD_SYNC_TIME           = 0X05, /* 同步时间 APP->MCU */
    WIFI_CMD_REQUEST_APP_TIME    = 0X06, /* MCU主动请求同步时间 */
    WIFI_CMD_REQUEST_WIFI_MAC    = 0X07, /* MCU获取WIFI MAC地址 */
    WIFI_CMD_REQUEST_MAC_TIME    = 0X08, /* WIFI获取MCU时间 */
    WIFI_CMD_ILLEGAL_MESSAGES    = 0X0E, /* 非法消息 */
    WIFI_CMD_OTA_MCU_START       = 0X0F, /* WIFI升级MCU 开始升级 */
    WIFI_CMD_OTA_MCU_DATA        = 0X10, /* WIFI升级MCU 数据包 */
    WIFI_CMD_OTA_MCU_END         = 0X11, /* WIFI升级MCU 结束升级 */
    WIFI_CMD_APP_OTA_WIFI        = 0X12, /* APP升级WIFI模组 */
    /* 设备控制&查询 */
    WIFI_CMD_READ_DEVICES_STATE  = 0X30, /* WIFI模组读取设备当前状态 */
    WIFI_CMD_CONTROL_DEVICES     = 0X31, /* WIFI模组控制设备 */
    WIFI_CMD_MCU_REPORT          = 0X32, /* MCU主动上报设备状态 */
} WIFI_CMD_LIST;

/* MCU配置WIFI */
typedef enum WIFI_MODE {
    RESTORE_FACTORY_SETTINGS  = 0X01, /* 恢复出厂设置 */
    REBOOTING_THE_WIFI_MODULE = 0X02, /* 重启WIFI模块 */
    ENTER_HIBERNATION_MODE    = 0X04, /* WIFI进入休眠模式 */
    ENTER_FACTORY_TEST_MODE   = 0X08, /* WIFI进入厂测模式 */
    ENTER_EASYLINK_MODE       = 0X0A, /* WIFI进入EASYLINK模式 */
} WIFI_MODE;

/* 错误码 */
typedef enum WIFI_ERR_CODE {
    DEVICE_TYPE_ERROR, /* 设备类型错误 */
    DEVICE_NUM_ERROR,  /* 设备型号错误 */
    VOID_COMMAND,      /* 命令不可识别 */
} WIFI_ERR_CODE;

#pragma pack (1) /* 设置字节对齐为1字节 */

/* wifi模组状态 WIFI_CMD_WIFI_STATE_CHANGE*/
typedef struct WIFI_STATUS {
    uint8_t wifiMode;    /* wifi模式 bit0：station，bit1：ap，bit2：easylink*/
    uint8_t wifiLink;    /* 0:wifi未连接路由器 1:连接 2：正在连接 */
    uint8_t wifiRes[6];  /* 预留 */
} WIFI_STATUS;

typedef struct WIFI_TIME {
    UINT16_T year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
} WIFI_TIME;

class WIFI_MAC_ADDR {
public:
    uint8_t macAddress[6];
    std::string toString() {
        std::string result;
        char data[5] = { 0 };
        for (size_t i = 0; i < 5; i++)
        {
            snprintf(data, sizeof(data), "%02x:", macAddress[i]);
            result.append(data);
        }
        snprintf(data, sizeof(data), "%02x", macAddress[5]);
        result.append(data);
        return result;
    }
};

typedef struct WIFI_WORK_TIME {
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
} WIFI_WORK_TIME;

/* 蒸烤微状态信息 */
typedef struct WIFI_ZKW_STATUS {
    uint8_t systemStatus;  /* 0/1/2 关机/待机/烹饪 */
    uint8_t workStatus;    /* 工作状态 */
    uint8_t stovetopLamps; /* 炉灯 0/1 关/开 */
    uint8_t waterTankActuators; /* 水箱推杆 0/1/2/3 关闭/停在中途/动作中/开启 */
    UINT16_T workingMode; /* 工作模式 */
    uint8_t cloudRecipesId[12]; /* 云菜谱ID */
    uint8_t modeAttributes; /* 模式属性 */
    uint8_t fastWarmUp;/* 快速预热 0/1 非/快速预热中 */
    WIFI_WORK_TIME workTime; /* 工作时间 */
    WIFI_WORK_TIME resStartTime; /* 预约开始时间 */
    WIFI_WORK_TIME remTime; /* 工作剩余时间 */
    WIFI_WORK_TIME remMultiPhase; /* 多段烹饪剩余时间 */
    uint8_t setUpTemp_1;/* 设定温度值 1 */
    uint8_t setUpTemp_2;/* 设定温度值 2（预留） */
    uint8_t tempSensors_1; /* 温度传感器 1 */
    uint8_t tempSensors_2; /* 温度传感器 2（预留） */
    uint8_t gatingStatus; /* 门控状态 0/1 关/开 */
    uint8_t errorCode; /* 故障号 */
    uint8_t waterShortage; /* 0：不缺水 1：缺水 */
    uint8_t waterTankLocation; /* 水箱位置 0/1 已推到位/未推到位 */
    struct {
        uint8_t Recordings:4;/* 录制状态 */
        uint8_t Playback:4; /* 播放状态 */
    } recipeRecordingStatus;/* 菜谱录制状态 */
    uint8_t recipePlaybackSteps; /* 菜谱播放步骤 */
    uint8_t micDefFlipTip; /* 微波解冻翻面提示 0/1 无/提示翻面 */
    uint8_t RESERVED[2];/* 预留 */
} WIFI_ZKW_STATUS;

/* WIFI模组控制ZKW 标志位 1是，0否 */
typedef struct WIFI_ATTR_FLAGS {
    uint8_t onOffSys:1; /* 设定开/关机 */
    uint8_t cancelJob:1; /* 开始暂停取消 烹饪/预约 */
    uint8_t stovetopLamps:1;/* 设定灯状态 */
    uint8_t waterTankPushRod:1; /* 设定水箱推杆状态 */
    uint8_t operatingMode:1; /* 是否设定工作模式 */
    uint8_t currentRecipe:1; /* 是否设定当前菜谱 */
    uint8_t setTotalWorkingTime:1; /* 是否设定总时间 */
    uint8_t appointmentStartTime:1; /* 是否设定开始时间 */
    uint8_t setTemperatureValue_1:1; /* 是否设定温度 1 */
    uint8_t setTemperatureValue_2:1; /* 是否设定温度 2 */
    uint8_t quickWarmUp:1; /* 是否快速预热 */
    uint8_t modeAttributes:1; /* 是否设定模式属性 */
    uint8_t RESERVED_1:1; /* 预留 */
    uint8_t RESERVED_2:1; /* 预留 */
} WIFI_ATTR_FLAGS;

/* WIFI模组控制ZKW 数据值，相关标志位打开有效 */
typedef struct WIFI_ATTR_VALS {
    uint8_t systemStatus;  /* 1/2/3 开机/待机/关机 */
    uint8_t workStatus;    /* 1/2/3/4/5 开始/暂停/取消/立即【烹饪】 取消预约 */
    uint8_t stovetopLamps; /* 炉灯 预留 */
    uint8_t waterTankActuators; /* 水箱推杆 预留 */
    UINT16_T workingMode; /* 工作模式 */
    uint8_t modeAttributes; /* 模式属性 */
    uint8_t fastWarmUp;/* 快速预热 0/1 不启动/启动 */
    uint8_t cloudRecipesId[12]; /* 云菜谱ID */
    WIFI_WORK_TIME workTime; /* 工作时间 */
    WIFI_WORK_TIME resStartTime; /* 预约开始时间 */
    uint8_t setUpTemp_1;/* 设定温度值 1 */
    uint8_t setUpTemp_2;/* 设定温度值 2（预留） */
    uint8_t RESERVED_1;/* 预留 */
    uint8_t RESERVED_2;/* 预留 */
} WIFI_ATTR_VALS;

/* wifi模组串口数据包 */
typedef struct WIFI_COMM_PACKAGE_T {
    UINT16_T    header;
    UINT16_T    len;
    UINT16_T    type;
    uint8_t     cmd;
    uint8_t     stat;
    UINT16_T    flags;
    uint8_t     payload[WIFI_COMM_MAX_PAYLOAD_NUM];
    UINT16_T    crc;/* 从header开始 */
} WIFI_COMM_PACKAGE_T;

#pragma pack () /* 恢复默认字节对齐方式 */

class WifiTransfer
{
private:
    WifiTransfer(/* args */);
    ~WifiTransfer();
    static WifiTransfer* instance;

    void replyToDeviceInformation(void); /* 回复设备信息 */
    void sendIllegalMessages(WIFI_ERR_CODE errCode); /* 恢复非法消息通知 */
    void wifiStatusChangeProcessing(void); /* wifi状态变化处理 */
    void wifiConfigurations(WIFI_MODE wifiMode, std::vector<uint8_t> attr); /* 配置wifi */
    void wifiSyncTime(WIFI_TIME wifiTime); /* 同步MCU时间 */
    void sendMcuTime(void); /* 将当前MCU时间发送给WIFI */
    void wifiRequestSyncTime(void); /* 请求同步时间 */
    void getWifiMacAddress(void); /* 获取wifi mac 地址 */
    void syncFactoryTestResults();/* 接受到wifi长测结果 */
    void sendZKWStatusInformation();/* 发送蒸烤微状态信息到WIFI模组 */
    void controlZKW();/* wifi控制ZKW */

    size_t wifi_memcpy(void *dst, const void *src, size_t siz);

    bool crc_flag;
    bool firstStarted;

    WIFI_STATUS wifiStatus; /* wifi状态 */
    WIFI_MAC_ADDR wifiMacAddr;/* wifi MAC 地址 */

public:
    static WifiTransfer* getInstance();
    /* >>CommUartCallback */
    bool transmitCommBuffer(void *buffer, int length);
    bool sendDataPeriodically(void);/* send data periodcially*/
    bool analyseCommBuffer(UartString* commBuffer);
    /* >>CommUartCallback */

    void wifiSendPacket(uint8_t cmd, uint8_t stat, UINT16_T flags, void *buffer, int length);

    void start(void);
    void stop(void);
};

void wifi_test();
void uniontext();

#endif 